ETLãã€ãã©ã€ã³ã«ãããåå®å šæ§ã®ããããŒã¿å€æãæ¢æ±ããŸããéçåä»ãã«ãããå ç¢ã§ä¿¡é Œæ§ãé«ãä¿å®ããããããŒã¿ã¯ãŒã¯ãããŒãå®è£ ããããŒã¿å質ãåäžããããšã©ãŒãåæžããæ¹æ³ãåŠã³ãŸãã
ç±»åå®å šçã§ããŒã¿å€æ: 粟å¯ãªETLãã€ãã©ã€ã³ã®å®è£
ããŒã¿ãšã³ãžãã¢ãªã³ã°ã®çµ¶ããé²åããç¶æ³ã«ãããŠãExtract, Transform, Load (ETL) ãã€ãã©ã€ã³ã¯ãåæãšæææ±ºå®ã®ããã®ããŒã¿ãçµ±åããã³æºåããããã®åºç€ã§ããç¶ããŠããŸããããããåŸæ¥ã®ETLã¢ãããŒãã¯ãããŒã¿å質ãå®è¡æãšã©ãŒãä¿å®æ§ã«é¢ããåé¡ã«ããæ©ãŸãããŠããŸããåå®å šæ§ã®ããããŒã¿å€ææè¡ãæ¡çšããããšã¯ããããã®èª²é¡ã«å¯Ÿãã匷åãªãœãªã¥ãŒã·ã§ã³ãæäŸããå ç¢ã§ä¿¡é Œæ§ãé«ãã¹ã±ãŒã©ãã«ãªããŒã¿ãã€ãã©ã€ã³ã®äœæãå¯èœã«ããŸãã
åå®å šæ§ã®ããããŒã¿å€æãšã¯ïŒ
åå®å šæ§ã®ããããŒã¿å€æã¯ãETLããã»ã¹å šäœã§ããŒã¿ãæåŸ ãããã¹ããŒããšå¶çŽã«æºæ ããããšãä¿èšŒããããã«ãéçåä»ããæŽ»çšããŸãããã®ããã¢ã¯ãã£ããªã¢ãããŒãã¯ããã€ãã©ã€ã³å šäœã«äŒæããŠäžæµã®ããŒã¿ãç Žæãããåã«ãã³ã³ãã€ã«æãŸãã¯å®è¡ã®åææ®µéã§æœåšçãªãšã©ãŒãæ€åºããŸãã
åå®å šæ§ã®ããããŒã¿å€æã®äž»ãªå©ç¹:
- ããŒã¿å質ã®åäž: å倿ã¹ãããã§ããŒã¿åãšæ§é ãæ€èšŒããããšã«ãããããŒã¿ã®äžè²«æ§ãšæŽåæ§ã匷å¶ããŸãã
- å®è¡æãšã©ãŒã®åæž: åé¢é£ã®ãšã©ãŒãæ©æã«æ€åºãããã€ãã©ã€ã³å®è¡äžã®äºæããªãé害ãé²ããŸãã
- ä¿å®æ§ã®åäž: ã³ãŒãã®æç¢ºããšå¯èªæ§ãåäžãããETLãã€ãã©ã€ã³ã®çè§£ããããã°ã倿Žã容æã«ããŸãã
- ä¿¡é Œæ§ã®åäž: 倿ãããããŒã¿ã®æ£ç¢ºæ§ãšä¿¡é Œæ§ã«å¯Ÿãããã倧ããªä¿èšŒãæäŸããŸãã
- ã³ã©ãã¬ãŒã·ã§ã³ã®åäž: æç¢ºãªããŒã¿å¥çŽãæäŸããããšã«ãããããŒã¿ãšã³ãžãã¢ãšããŒã¿ãµã€ãšã³ãã£ã¹ãéã®ã³ã©ãã¬ãŒã·ã§ã³ãä¿é²ããŸãã
åå®å šæ§ã®ããETLãã€ãã©ã€ã³ã®å®è£ : äž»èŠãªæŠå¿µ
åå®å šæ§ã®ããETLãã€ãã©ã€ã³ã®æ§ç¯ã«ã¯ãããã€ãã®äž»èŠãªæŠå¿µãšæè¡ãå«ãŸããŸãã
1. ã¹ããŒãå®çŸ©ãšæ€èšŒ
åå®å šæ§ã®ããETLã®åºç€ã¯ãããŒã¿ã®æç€ºçãªã¹ããŒããå®çŸ©ããããšã«ãããŸããã¹ããŒãã¯ãååãããŒã¿åïŒäŸ: æŽæ°ãæååãæ¥ä»ïŒãããã³å¶çŽïŒäŸ: nulläžå¯ãäžæïŒãå«ããããŒã¿ã®æ§é ãšããŒã¿åãèšè¿°ããŸããApache AvroãProtocol BuffersããŸãã¯èšèªåºæã®ã©ã€ãã©ãªïŒScalaã®ã±ãŒã¹ã¯ã©ã¹ãPythonã®Pydanticãªã©ïŒã®ãããªã¹ããŒãå®çŸ©ããŒã«ã䜿çšãããšãããŒã¿ã®æ§é ãæ£åŒã«å®£èšã§ããŸãã
äŸ:
顧客ããŒã¿ããŒã¹ããããŒã¿ãæœåºããŠãããšããŸããCustomerããŒã¿ã®ã¹ããŒããæ¬¡ã®ããã«å®çŸ©ããå ŽåããããŸãã
{
"type": "record",
"name": "Customer",
"fields": [
{"name": "customer_id", "type": "int"},
{"name": "first_name", "type": "string"},
{"name": "last_name", "type": "string"},
{"name": "email", "type": "string"},
{"name": "registration_date", "type": "string"} // ISO 8601圢åŒãæ³å®
]
}
倿ãè¡ãåã«ãåä¿¡ããŒã¿ããã®ã¹ããŒãã«å¯ŸããŠæ€èšŒããå¿ èŠããããŸããããã«ãããããŒã¿ãæåŸ ãããæ§é ãšããŒã¿åã«æºæ ããŠããããšãä¿èšŒãããŸããã¹ããŒãã«éåããããŒã¿ã¯æåŠãããããé©åã«åŠçãããå¿ èŠããããŸãïŒäŸ: 調æ»ã®ããã«ãã°ã«èšé²ãããŸãïŒã
2. éçåä»ããšããŒã¿å¥çŽ
ScalaãJavaãããã³PythonïŒMyPyã®ãããªããŒã«ã§ãŸããŸãæ¡çšãããŠããïŒã®ãããªèšèªã«ãã£ãŠæäŸãããéçåä»ãã¯ãåå®å šæ§ã匷å¶ããäžã§éèŠãªåœ¹å²ãæãããŸããéçåã䜿çšããããšã«ãããå倿ã¹ãããã®æåŸ ãããå ¥åããã³åºååãæå®ããããŒã¿å¥çŽãå®çŸ©ã§ããŸãã
äŸ (Scala):
case class Customer(customerId: Int, firstName: String, lastName: String, email: String, registrationDate: String)
def validateEmail(customer: Customer): Option[Customer] = {
if (customer.email.contains("@") && customer.email.contains(".")) {
Some(customer)
} else {
None // ç¡å¹ãªã¡ãŒã«
}
}
ãã®äŸã§ã¯ãvalidateEmail颿°ã¯ãCustomerãªããžã§ã¯ããå
¥åãšããŠåãåããæå¹ãªé¡§å®¢ãŸãã¯äœãè¿ããªãããšã瀺ãOption[Customer]ãè¿ãããšãæç€ºçã«è¿°ã¹ãŠããŸããããã«ãããã³ã³ãã€ã©ã¯é¢æ°ãæ£ãã䜿çšãããŠããããšãããã³åºåãé©åã«åŠçãããŠããããšã確èªã§ããŸãã
3. 颿°åããã°ã©ãã³ã°ã®åå
äžå€æ§ãçŽç²é¢æ°ãå¯äœçšã®åé¿ãªã©ã®é¢æ°åããã°ã©ãã³ã°ã®ååã¯ãåå®å šæ§ã®ããããŒã¿å€æã«ç¹ã«é©ããŠããŸããäžå€ããŒã¿æ§é ã¯ãããŒã¿ãã€ã³ãã¬ãŒã¹ã§å€æŽãããªãããšãä¿èšŒããäºæããªãå¯äœçšãé²ãã倿ããã»ã¹ã«ã€ããŠã®æšè«ã容æã«ããŸããåãå ¥åã«å¯ŸããŠåžžã«åãåºåãè¿ããå¯äœçšããªãçŽç²é¢æ°ã¯ãäºæž¬å¯èœæ§ãšãã¹ãå¯èœæ§ãããã«åäžãããŸãã
äŸ (颿°åããã°ã©ãã³ã°ã䜿çšããPython):
from typing import NamedTuple, Optional
class Customer(NamedTuple):
customer_id: int
first_name: str
last_name: str
email: str
registration_date: str
def validate_email(customer: Customer) -> Optional[Customer]:
if "@" in customer.email and "." in customer.email:
return customer
else:
return None
ããã§ã¯ãCustomerã¯ååä»ãã¿ãã«ã§ãããäžå€ããŒã¿æ§é ã衚ããŸããvalidate_email颿°ãçŽç²é¢æ°ã§ããCustomerãªããžã§ã¯ããåãåããå
ã®Customerãªããžã§ã¯ãã倿Žããããä»ã®å¯äœçšãåŒãèµ·ããããããããšãªããã¡ãŒã«æ€èšŒã«åºã¥ããŠãªãã·ã§ã³ã®Customerãªããžã§ã¯ããè¿ããŸãã
4. ããŒã¿å€æã©ã€ãã©ãªãšãã¬ãŒã ã¯ãŒã¯
ããã€ãã®ã©ã€ãã©ãªãšãã¬ãŒã ã¯ãŒã¯ã¯ãåå®å šæ§ã®ããããŒã¿å€æãä¿é²ããŸãããããã®ããŒã«ã¯ãã¹ããŒãå®çŸ©ãããŒã¿æ€èšŒãããã³çµã¿èŸŒã¿åãã§ãã¯ãåãã倿颿°ã®ãããªæ©èœãæäŸããããšããããããŸãã
- Scalaãšã®Apache Spark: Scalaã®åŒ·åãªåã·ã¹ãã ãšçµã¿åãããSparkã¯ãåå®å šæ§ã®ããETLãã€ãã©ã€ã³ãæ§ç¯ããããã®åŒ·åãªãã©ãããã©ãŒã ãæäŸããŸããSparkã®Dataset APIã¯ãããŒã¿å€æã®ããã®ã³ã³ãã€ã«æåå®å šæ§ãæäŸããŸãã
- Apache Beam: Beamã¯ããããããã³ã¹ããªãŒãã³ã°ããŒã¿åŠçã®äž¡æ¹ã«å¯Ÿå¿ããçµ±äžããã°ã©ãã³ã°ã¢ãã«ãæäŸããããŸããŸãªå®è¡ãšã³ãžã³ïŒSparkãFlinkãGoogle Cloud Dataflowãªã©ïŒããµããŒãããŸããBeamã®åã·ã¹ãã ã¯ãç°ãªãåŠçã¹ããŒãžéã§ããŒã¿ã®äžè²«æ§ã確ä¿ããã®ã«åœ¹ç«ã¡ãŸãã
- dbt (Data Build Tool): dbtèªäœã¯ããã°ã©ãã³ã°èšèªã§ã¯ãããŸããããSQLãšJinjaã䜿çšããŠããŒã¿ãŠã§ã¢ããŠã¹ã®ããŒã¿ã倿ããããã®ãã¬ãŒã ã¯ãŒã¯ãæäŸããŸããããè€éãªå€æãšããŒã¿æ€èšŒã®ããã«ãåå®å šæ§ã®ããèšèªãšçµ±åã§ããŸãã
- PydanticãšMyPyã䜿çšããPython: Pydanticã¯ãPythonã®åã¢ãããŒã·ã§ã³ã䜿çšããŠããŒã¿æ€èšŒãšèšå®ç®¡çãå®çŸ©ã§ããŸããMyPyã¯Pythonã³ãŒãã®éçåãã§ãã¯ãæäŸããå®è¡åã«åé¢é£ã®ãšã©ãŒãæ€åºã§ããŸãã
åå®å šæ§ã®ããETLãã€ãã©ã€ã³ã®å®è·µäŸ
ããŸããŸãªãã¯ãããžãŒã䜿çšããŠåå®å šæ§ã®ããETLãã€ãã©ã€ã³ãå®è£ ããæ¹æ³ã説æããŸãã
äŸ1: Apache SparkãšScalaã䜿çšããåå®å šæ§ã®ããETL
ãã®äŸã§ã¯ã顧客ããŒã¿ãCSVãã¡ã€ã«ããèªã¿èŸŒã¿ãå®çŸ©æžã¿ã®ã¹ããŒãã«å¯ŸããŠããŒã¿ãæ€èšŒããããŒã¿ãParquetãã¡ã€ã«ã«å€æããç°¡åãªETLãã€ãã©ã€ã³ã瀺ããŸããããã¯ãSparkã®Dataset APIã䜿çšããŠã³ã³ãã€ã«æåå®å šæ§ã掻çšããŸãã
import org.apache.spark.sql.{Dataset, SparkSession}
import org.apache.spark.sql.types._
import org.apache.spark.sql.functions._
case class Customer(customerId: Int, firstName: String, lastName: String, email: String, registrationDate: String)
object TypeSafeETL {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("TypeSafeETL").master("local[*]").getOrCreate()
import spark.implicits._
// ã¹ããŒããå®çŸ©
val schema = StructType(Array(
StructField("customerId", IntegerType, nullable = false),
StructField("firstName", StringType, nullable = false),
StructField("lastName", StringType, nullable = false),
StructField("email", StringType, nullable = false),
StructField("registrationDate", StringType, nullable = false)
))
// CSVãã¡ã€ã«ãèªã¿èŸŒã
val df = spark.read
.option("header", true)
.schema(schema)
.csv("data/customers.csv")
// Dataset[Customer]ã«å€æ
val customerDS: Dataset[Customer] = df.as[Customer]
// 倿: ã¡ãŒã«ãæ€èšŒ
val validCustomers = customerDS.filter(customer => customer.email.contains("@") && customer.email.contains("."))
// ããŒã: Parquetã«æžã蟌ã
validCustomers.write.parquet("data/valid_customers.parquet")
spark.stop()
}
}
説æ:
- ã³ãŒãã¯ãããŒã¿æ§é ã衚ã
Customerã±ãŒã¹ã¯ã©ã¹ãå®çŸ©ããŸãã - å®çŸ©æžã¿ã®ã¹ããŒããæã€CSVãã¡ã€ã«ãèªã¿èŸŒã¿ãŸãã
- DataFrameã
Dataset[Customer]ã«å€æããŸããããã«ãããã³ã³ãã€ã«æåå®å šæ§ãæäŸãããŸãã - æå¹ãªã¡ãŒã«ã¢ãã¬ã¹ãæã€é¡§å®¢ã®ã¿ãå«ããããã«ããŒã¿ããã£ã«ã¿ãªã³ã°ããŸãã
- 倿ãããããŒã¿ãParquetãã¡ã€ã«ã«æžã蟌ã¿ãŸãã
äŸ2: PythonãPydanticãããã³MyPyã䜿çšããåå®å šæ§ã®ããETL
ãã®äŸã§ã¯ãPydanticã䜿çšããŠããŒã¿æ€èšŒãè¡ããMyPyã䜿çšããŠéçåãã§ãã¯ãè¡ãããšã«ãããPythonã§åå®å šæ§ãå®çŸããæ¹æ³ã瀺ããŸãã
from typing import List, Optional
from pydantic import BaseModel, validator
class Customer(BaseModel):
customer_id: int
first_name: str
last_name: str
email: str
registration_date: str
@validator("email")
def email_must_contain_at_and_dot(cls, email: str) -> str:
if "@" not in email or "." not in email:
raise ValueError("ç¡å¹ãªã¡ãŒã«åœ¢åŒ")
return email
def load_data(file_path: str) -> List[dict]:
# ãã¡ã€ã«ããã®ããŒã¿èªã¿èŸŒã¿ãã·ãã¥ã¬ãŒã (å®éã®ãã¡ã€ã«èªã¿èŸŒã¿ã«çœ®ãæããŠãã ãã)
return [
{"customer_id": 1, "first_name": "John", "last_name": "Doe", "email": "john.doe@example.com", "registration_date": "2023-01-01"},
{"customer_id": 2, "first_name": "Jane", "last_name": "Smith", "email": "jane.smith@example.net", "registration_date": "2023-02-15"},
{"customer_id": 3, "first_name": "Peter", "last_name": "Jones", "email": "peter.jonesexample.com", "registration_date": "2023-03-20"},
]
def transform_data(data: List[dict]) -> List[Customer]:
customers: List[Customer] = []
for row in data:
try:
customer = Customer(**row)
customers.append(customer)
except ValueError as e:
print(f"è¡ã®æ€èšŒãšã©ãŒ: {row} - {e}")
return customers
def save_data(customers: List[Customer], file_path: str) -> None:
# ãã¡ã€ã«ãžã®ããŒã¿ä¿åãã·ãã¥ã¬ãŒã (å®éã®ãã¡ã€ã«æžã蟌ã¿ã«çœ®ãæããŠãã ãã)
print(f"{len(customers)}ä»¶ã®æå¹ãªé¡§å®¢ã{file_path}ã«ä¿åããŠããŸã")
for customer in customers:
print(customer.json())
if __name__ == "__main__":
data = load_data("data/customers.json")
valid_customers = transform_data(data)
save_data(valid_customers, "data/valid_customers.json")
説æ:
- ã³ãŒãã¯ãPydanticã®
BaseModelã䜿çšããŠCustomerã¢ãã«ãå®çŸ©ããŸãããã®ã¢ãã«ã¯ãããŒã¿ã«å¯Ÿããåå¶çŽã匷å¶ããŸãã - æ€èšŒé¢æ°ã¯ãã¡ãŒã«ãã£ãŒã«ãã«ã@ããšã.ãã®äž¡æ¹ãå«ãŸããŠããããšã確èªããããã«äœ¿çšãããŸãã
transform_data颿°ã¯ãå ¥åããŒã¿ããCustomerãªããžã§ã¯ããäœæããããšããŸããããŒã¿ãã¹ããŒãã«æºæ ããŠããªãå ŽåãValueErrorãçºçããŸãã- MyPyã¯ãã³ãŒããéçã«åãã§ãã¯ããå®è¡åã«æœåšçãªåãšã©ãŒãæ€åºããããã«äœ¿çšã§ããŸãã
mypy your_script.pyãå®è¡ããŠãã¡ã€ã«ããã§ãã¯ããŠãã ããã
åå®å šæ§ã®ããETLãã€ãã©ã€ã³ã®ãã¹ããã©ã¯ãã£ã¹
åå®å šæ§ã®ããããŒã¿å€æã®ã¡ãªãããæå€§éã«æŽ»çšããããã«ã次ã®ãã¹ããã©ã¯ãã£ã¹ãæ€èšããŠãã ããã
- æ©æã«ã¹ããŒããå®çŸ©: ããŒã¿ãœãŒã¹ãšã¿ãŒã²ããã®æç¢ºã§å æ¬çãªã¹ããŒããå®çŸ©ããããšã«æéãæè³ããŠãã ããã
- åã¹ããŒãžã§ããŒã¿ãæ€èšŒ: å倿ã¹ãããã§ããŒã¿æ€èšŒãã§ãã¯ãå®è£ ããŠããšã©ãŒãæ©æã«æ€åºããŠãã ããã
- é©åãªããŒã¿åã䜿çš: ããŒã¿ãæ£ç¢ºã«è¡šããå¿ èŠã«å¿ããŠå¶çŽã匷å¶ããããŒã¿åãéžæããŠãã ããã
- 颿°åããã°ã©ãã³ã°ãæ¡çš: 颿°åããã°ã©ãã³ã°ã®ååãæŽ»çšããŠãäºæž¬å¯èœã§ãã¹ãå¯èœãªå€æãäœæããŠãã ããã
- ãã¹ããèªåå: ETLãã€ãã©ã€ã³ã®æ£ç¢ºæ§ã確ä¿ããããã«ãå æ¬çãªåäœãã¹ããšçµ±åãã¹ããå®è£ ããŠãã ããã
- ããŒã¿å質ãç£èŠ: ããŒã¿å質ã¡ããªã¯ã¹ãç¶ç¶çã«ç£èŠããŠãããŒã¿ã®åé¡ãããã¢ã¯ãã£ãã«æ€åºããã³å¯ŸåŠããŠãã ããã
- é©åãªããŒã«ãéžæ: 匷åãªåå®å šæ§ãšããŒã¿æ€èšŒæ©èœãæäŸããããŒã¿å€æã©ã€ãã©ãªãšãã¬ãŒã ã¯ãŒã¯ãéžæããŠãã ããã
- ãã€ãã©ã€ã³ãææžå: ã¹ããŒãå®çŸ©ã倿ããžãã¯ãããŒã¿å質ãã§ãã¯ãå«ãETLãã€ãã©ã€ã³ã培åºçã«ææžåããŠãã ãããæç¢ºãªææžã¯ãä¿å®æ§ãšã³ã©ãã¬ãŒã·ã§ã³ã«ãšã£ãŠéèŠã§ãã
課é¡ãšèæ ®äºé
åå®å šæ§ã®ããããŒã¿å€æã¯å€ãã®å©ç¹ãæäŸããŸãããããã€ãã®èª²é¡ãšèæ ®äºé ãæç€ºããŸãã
- åŠç¿æ²ç·: åå®å šæ§ã®ããèšèªãšãã¬ãŒã ã¯ãŒã¯ãæ¡çšããã«ã¯ãããŒã¿ãšã³ãžãã¢ã«ãšã£ãŠåŠç¿æ²ç·ãå¿ èŠã«ãªãå ŽåããããŸãã
- éçºå·¥æ°ã®å¢å : åå®å šæ§ã®ããETLãã€ãã©ã€ã³ã®å®è£ ã«ã¯ãåŸæ¥ã®Ãã¢ãããŒããšæ¯èŒããŠãããå€ãã®åæéçºå·¥æ°ãå¿ èŠã«ãªãå ŽåããããŸãã
- ããã©ãŒãã³ã¹ãªãŒããŒããã: ããŒã¿æ€èšŒãšåãã§ãã¯ã¯ãããããã®ããã©ãŒãã³ã¹ãªãŒããŒããããããããå¯èœæ§ããããŸããããããããŒã¿å質ã®åäžãšå®è¡æãšã©ãŒã®åæžã«ããã¡ãªããã¯ããã®ã³ã¹ããäžåãããšããããããŸãã
- ã¬ã¬ã·ãŒã·ã¹ãã ãšã®çµ±å: 匷åãªåä»ãããµããŒãããŠããªãã¬ã¬ã·ãŒã·ã¹ãã ãšåå®å šæ§ã®ããETLãã€ãã©ã€ã³ãçµ±åããããšã¯å°é£ãªå ŽåããããŸãã
- ã¹ããŒãã®é²å: ã¹ããŒãã®é²åïŒã€ãŸããæéã®çµéã«äŒŽãããŒã¿ã¹ããŒãã®å€æŽïŒã®åŠçã«ã¯ãæ éãªèšç»ãšå®è£ ãå¿ èŠã§ãã
çµè«
åå®å šæ§ã®ããããŒã¿å€æã¯ãå ç¢ã§ä¿¡é Œæ§ãé«ããä¿å®å¯èœãªETLãã€ãã©ã€ã³ãæ§ç¯ããããã®åŒ·åãªã¢ãããŒãã§ããéçåä»ããã¹ããŒãæ€èšŒãããã³é¢æ°åããã°ã©ãã³ã°ã®ååãæŽ»çšããããšã«ãããããŒã¿å質ãå€§å¹ ã«åäžãããå®è¡æãšã©ãŒãåæžããããŒã¿ãšã³ãžãã¢ãªã³ã°ã¯ãŒã¯ãããŒã®å šäœçãªå¹çãé«ããããšãã§ããŸããããŒã¿éãšè€éæ§ãå¢å€§ãç¶ããã«ã€ããŠãããŒã¿é§ååã€ã³ãµã€ãã®æ£ç¢ºæ§ãšä¿¡é Œæ§ã確ä¿ããããã«ãåå®å šæ§ã®ããããŒã¿å€æãæ¡çšããããšããŸããŸãéèŠã«ãªããŸãã
Apache SparkãApache BeamãPydanticã䜿çšããPythonããŸãã¯ãã®ä»ã®ããŒã¿å€æããŒã«ã䜿çšããŠãããã©ããã«ããããããETLãã€ãã©ã€ã³ã«åå®å šæ§ã®ãããã©ã¯ãã£ã¹ãçµã¿èŸŒãããšã¯ãããå埩åããã䟡å€ã®ããããŒã¿ã€ã³ãã©ã¹ãã©ã¯ãã£ã«ã€ãªãããŸããããã§æŠèª¬ãããŠããäŸãšãã¹ããã©ã¯ãã£ã¹ãæ€èšããŠãåå®å šæ§ã®ããããŒã¿å€æãžã®æ ãå§ããããŒã¿åŠçã®å質ãåäžãããŠãã ããã